home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
asm_n_z.zip
/
SCRNFLIP.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-03-01
|
13KB
|
372 lines
; This program is described in BYTE, November 1983, Pages 99 - 116.
; Article is entitled "ENHANCING SCREEN DISPLAYS FOR THE IBM PC",
; author is Tim Field.
; Define interrupt vectors for both keyboard interrupt 16H and screen
; interrupt 10H. Both are in segment 0:
KEYVECT SEGMENT AT 0 ;Define KEYBOARD int. vector
ORG 16H*4
KEYINT LABEL DWORD
KEYVECT ENDS
SCRVECT SEGMENT AT 0 ;Define SCREEN int. vector
ORG 10H*4
SCRINT LABEL DWORD
SCRVECT ENDS
; Define constants:
BW_VAL EQU 07H ;Standard B&W attribute
EQUIP_FLAG EQU 410H ;RAM address of equipment stat
CHK_MODE EQU 15 ;INT fn: Check screen mode
MONO_MODE EQU 7 ;Mode 7 = monochrome monitor
COLOR_ADPT EQU 3 ;Modes 0-3: non-graphics color
; Start code area:
CODE SEGMENT PARA ;Start code at offset 100H
ASSUME CS:CODE ;from starting segment; leaves
ORG 100H ;room for PSP
KEY PROC FAR
; Initialization code - used only once during startup:
START:
JMP INIT_CODE ;Call initialization routine
; Define storage areas and data structures:
; Define keystroke scan codes for the five SCREEN functions:
FORE_INC DW 5E00H ;Foreground increment
BACK_INC DW 6000H ;Background increment
C80_40 DW 6200H ;80x25 to 40x25 flip-flop key
COL_MON DW 6400H ;COLOR/MONO flip-flop key
REPAINT DW 6600H ;Repaint scrn using curr. mode
CUR_MODE DW COL80_AREA ;Initialize starting mode
MONO_SET DW MONO_AREA ;Pointer to monochrome area
COLOR_SET DW COL80_AREA ;Pointer to active color area
SCRN_ATTR DB 70H ;Current screen attribute
SCRN_MODE DB 255 ;Save current screen mode
; Define structure used to contain information about 40 and 80 column color
; modes as well as monochrome mode:
S STRUC
CORNER DW 0 ;Defines COL/ROW count of
;characters for the monitor
BF DW 0 ;Colors of FORE and BACK
EQUIP DW 0 ;Equipment setting
MODE DW 0 ;AX value for setting the mode
S ENDS ;of the monitor
; Now set up three screen structures with default condition:
COL80_AREA S <5019H,0107H,20H,3> ;80x25 white FORE, blue BACK
COL40_AREA S <2819H,0107H,10H,1> ;40x25 brown FORE, black BACK
MONO_AREA S <5019H,0007H,30H,7> ;Monochrome, reverse video
KEY_CALL: DB 0EAH ;Far JMP address to KEYBOARD
DD 0 ;interrupt. See article
; Procedure KEY_RTNE intercepts keyboard interrupt and determines if the
; keystroke is one of the five SCREEN ones:
KEY_RTNE:
STI ;Turn on interrupts
CMP AH,0
JNE KEY_CALL
PUSH DS ;Save registers
PUSH BX
PUSH CX
PUSH DX
PUSH ES
PUSH DI
PUSH CS ;Point DS to CS segment by
POP DS ;PUSH / POP operation
ASSUME DS:CODE
INT_LOOP: ;IBM keyboard procedure
PUSHF ;expects an interrupt call
MOV BX,OFFSET KEY_CALL+1 ;Address to ROM keyboard code
CALL DWORD PTR [BX] ;Call keyboard routine
MOV BX,CUR_MODE ;Get current mode address
CMP AX,COL_MON ;See if COLOR/MON flip flop
JNE TEST_FORE ;key. Exit if not. Otherwise:
CMP BX,MONO_SET ;Flip flop screen mode
JE SET_COLOR ;If monochrome, swap to color
CMP MONO_SET,0 ;See if monochrome installed
JE NEXT_KEY ;Ignore command if not
MOV BX,MONO_SET ;Otherwise set up monochrome
JMP SHORT DO_CHG
SET_COLOR:
CMP COLOR_SET,0 ;See if COLOR monitor enabled
JE NEXT_KEY ;Skip if not
MOV BX,COLOR_SET ;Set up for color
DO_CHG:
CALL SCREEN_CHG ;Implement screen change
NEXT_KEY:
MOV AH,0 ;Set up to fetch keystroke
JMP INT_LOOP ;Fetch next key input
TEST_FORE:
PUSH AX ;Save registers
PUSH BX ;See if in GRAPHICS mode
MOV AH,CHK_MODE
INT 10H
POP BX ;Restore BX register
CMP AL,COLOR_ADPT ;If between 0-3, not graphics
JLE NOT_GRAPH
CMP AL,MONO_MODE ;Monochrome mode
JGE NOT_GRAPH
POP AX ;Restore stack
JMP DONE ;If color-graphics mode, do
NOT_GRAPH: ;not change modes
POP AX ;Restore AX
CMP AX,FORE_INC ;Increment FOREGROUND color?
JNE TEST_BACK ;Skip if not
CMP BX,COLOR_SET ;See if currently using color
JNE BW_FLOP ;If not, go deal with B&W
MOV AX,[BX].BF ;Gets BACK in AL, FORE in AH
EQ_FORE:
INC AL ;Increment FOREGROUND color
AND AL,7 ;Keep it within bounds
CMP AL,AH ;See if same as BACKGROUND
JE EQ_FORE ;Increment again if yes
MOV [BX].BF,AX ;Save back to structure
JMP DO_CHG ;Redraw the screen
TEST_BACK:
CMP AX,BACK_INC ;Increment BACKGROUND color?
JNE TEST_REPAINT ;Skip if not
CMP BX,COLOR_SET ;See if currently using color
JNE BW_FLOP ;If not, go deal with B&W
MOV AX,[BX].BF ;Gets BACK in AL, FORE in AH
EQ_BACK:
INC AH ;Increment BACKGROUND color
AND AH,7 ;Keep it within bounds
CMP AH,AL ;See if same as FOREGROUND
JE EQ_BACK ;Increment again if yes
MOV [BX].BF,AX ;Save back to structure
JMP DO_CHG ;Redraw the screen
BW_FLOP: ;Flip flop B&W monitor
MOV AX,[BX].BF ;BACK in AH, FORE in Al
XCHG AH,AL ;Swap FOREGROUND, BACKGROUND
MOV [BX].BF,AX ;Save back to structure
JMP DO_CHG ;Redraw the screen
TEST_REPAINT:
CMP AX,REPAINT ;Repaint the screen?
JE DO_CHG ;If yes, then repaint screen
TEST_80_40:
CMP AX,C80_40 ;80-40 flip flop key?
JNE DONE ;Exit if not
CMP BX,OFFSET COL40_AREA ;Is curr. pointer area 40x25?
JNE TST80 ;Skip if not
MOV BX,OFFSET COL80_AREA ;Otherwise, flip to 80x25
JMP SHORT SAVE_COL ;Save to COLOR_SET
TST80:
CMP BX,OFFSET COL80_AREA ;Is current 80x25 color?
JNE NEXT_KEY ;Ignore key if not
MOV BX,OFFSET COL40_AREA
SAVE_COL:
MOV COLOR_SET,BX ;Save to COLOR_SET
JMP SET_COLOR ;Implement
DONE:
POP DI ;Restore registers
POP ES
POP DX
POP CX
POP BX
POP DS
IRET ;Return from interrupt
KEY ENDP ;End of main routine
; This routine changes current monitor screen mode. On input, BX points to
; the current monitor structure:
SCREEN_CHG PROC NEAR
MOV AX,0 ;Get segment address for RAM
MOV ES,AX ;EQUIP_FLAG
MOV AX,ES:EQUIP_FLAG ;Get set of EQUIP flags
AND AL,0CFH ;Scrap current monitor flag
OR AX,[BX].EQUIP ;Set up new monitor flag
MOV ES:EQUIP_FLAG,AX ;Save back in RAM
MOV CUR_MODE,BX ;Indicate new mode
; Now set up attribute for FOREGROUND and BACKGROUND:
MOV DX,[BX].BF ;Get both FORE and BACK in DX
MOV CL,4 ;Shift count
SHL DH,CL ;Shift BACK into upper nibble
OR DH,DL ;Move FORE into lower nibble
MOV SCRN_ATTR,DH ;Save results
; See if we need to reset monitor (switching to new monitor?):
MOV AX,[BX].MODE ;Get screen mode
CMP AL,SCRN_MODE ;Compare with current mode
JE SET_ATTR ;Skip if the same
MOV SCRN_MODE,AL ;Otherwise, save current mode
INT 10H ;And reset to new monitor
SET_ATTR:
CALL CH_ATTR ;Change attributes of current
RET ;screen
SCREEN_CHG ENDP
; This routine repaints the active screen so that every character on the
; current screen is displayed with the new attributes. On input, BX points
; to the current monitor structure:
CH_ATTR PROC NEAR
; See if we need to redraw border for color mode
CMP BX,OFFSET MONO_SET ;In color?
JE NO_BORDER